<template>
  <div>
    <el-card style="height: 13%; line-height: 13%">
      <el-form
        style="
          display: flex;
          justify-content: space-between;
          align-items: center;
        "
      >
        <el-form-item label="用户名">
          <el-input
            @keyup.enter="getRoleInfo"
            placeholder="请输入职位名称"
            v-model.trim="roleName"
          ></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="getRoleInfo">搜索</el-button>
          <el-button size="default" @click="ResetInfo">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <el-card style="margin: 20px 0">
      <el-button type="primary" @click="roleAddNew" v-has="`btn.Role.add`">
        添加
      </el-button>
      <!-- Table -->
      <el-table
        :data="roleInfo"
        border
        style="margin: 20px 0"
        tooltip-effect="dark"
      >
        <el-table-column type="index" label="#"></el-table-column>
        <el-table-column prop="id" label="ID" align="center"></el-table-column>
        <el-table-column
          show-overflow-tooltip
          prop="roleName"
          label="用户角色"
          align="center"
        ></el-table-column>
        <el-table-column
          prop="createTime"
          label="创建时间"
          align="center"
        ></el-table-column>
        <el-table-column
          prop="updateTime"
          label="更新时间"
          align="center"
        ></el-table-column>
        <el-table-column label="操作" width="260px" align="center">
          <template #default="{ row }">
            <el-button
              type="primary"
              icon="User"
              size="small"
              @click="roleAcl(row)"
              v-has="`btn.Role.assgin`"
            >
              分配权限
            </el-button>
            <el-button
              type="primary"
              icon="Edit"
              size="small"
              @click="roleAddNew(row)"
              v-has="`btn.Role.update`"
              plain
            >
              编辑
            </el-button>
            <el-popconfirm
              :title="`确认删除用户角色'${row.roleName}?'`"
              cancel-button-text="取消"
              confirm-button-text="确认"
              icon="InfoFilled"
              @confirm="deleteRole(row)"
            >
              <template #reference>
                <el-button
                  type="danger"
                  icon="Delete"
                  size="small"
                  v-has="`btn.Role.remove`"
                ></el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
      <!-- Pagination -->
      <el-pagination
        size="default"
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[5, 10, 15]"
        :pager-count="7"
        layout="prev,pager,next,jumper,->,sizes,total"
        :total="total"
        :background="true"
        @size-change="sizeChange"
        @current-change="currentChange"
      ></el-pagination>
      <!-- 添加职位角色 -->
      <el-dialog
        v-model="visibale"
        :title="roleData.id ? '修改角色' : '添加角色'"
        height="500"
        :before-close="addCancle"
      >
        <template #default>
          <el-form
            style="margin: 20px 0; padding-right: 20px"
            ref="form"
            :model="roleData"
            :rules="rules"
          >
            <el-form-item label="角色名称" prop="roleName">
              <el-input type="text" v-model.trim="roleData.roleName" />
            </el-form-item>
          </el-form>
        </template>
        <template #footer>
          <el-button plain @click="addCancle">取消</el-button>
          <el-button type="primary" @click="addNewRole">确定</el-button>
        </template>
      </el-dialog>
      <el-drawer
        v-model="drawer"
        title="菜单与按钮权限分配"
        :before-close="addCancle"
      >
        <template #default>
          <div v-loading="load" style="height: 100%">
            <el-row :gutter="20">
              <el-col :span="6">用户角色:</el-col>
              <el-col :span="18">{{ roleData.roleName }}</el-col>
            </el-row>
            <el-tree
              ref="trees"
              style="max-width: 600px; margin-top: 20px"
              :data="data"
              show-checkbox
              node-key="id"
              default-expand-all
              :default-checked-keys="checkArr"
              :props="defaultProps"
            />
          </div>
        </template>
        <template #footer>
          <el-button @click="drawer = false">取消</el-button>
          <el-button type="primary" @click="updateRole">确认</el-button>
        </template>
      </el-drawer>
    </el-card>
  </div>
</template>

<script lang="ts" setup name="index">
import {
  AddOrUpdateRole,
  getRoleMenuById,
  reqRoleInfoLimits,
  reqAddUpdateAcl,
  deleteCurrentRole,
} from '@/api/acl/role'
import { ResponseMenuList, RoleRecords } from '@/api/acl/role/type'
import { ElMessage } from 'element-plus'
import { nextTick, onMounted, reactive, ref } from 'vue'
let roleName = ref('')
let currentPage = ref(1)
let pageSize = ref(5)
let total = ref(0)
let roleInfo = ref<RoleRecords[]>([])
let visibale = ref(false)
let form = ref<any>()
let roleData = ref<RoleRecords>({
  id: '',
  roleName: '',
})
let drawer = ref(false)
const defaultProps = {
  children: 'children',
  label: 'name',
}
let data = ref<ResponseMenuList>()
let checkArr = ref([])
let trees = ref<any>()
let load = ref(false)
// 页面Dom元素加载完毕后向服务器请求数据
onMounted(() => {
  getRoleInfo()
})
//初始化页面数据和搜索的方法
const getRoleInfo = async () => {
  const result = await reqRoleInfoLimits(
    currentPage.value,
    pageSize.value,
    roleName.value,
  )
  roleInfo.value = result.data.records
  total.value = result.data.total
}
//搜索框重置
const ResetInfo = () => {
  roleName.value = ''
  getRoleInfo()
}
// ----分页器每页显示多少条数据发生改变时
const sizeChange = () => {
  getRoleInfo()
}
//--当前页的页码发生改变时触发
const currentChange = () => {
  getRoleInfo()
}
//新增职位角色名称
const roleAddNew = (row: RoleRecords) => {
  if (row.id) {
    Object.assign(roleData.value, row)
  }
  visibale.value = true
  //清除验证信息
  nextTick(() => {
    form.value.clearValidate()
  })
}
//取消添加,清除数据
const addCancle = () => {
  Object.assign(roleData.value, {
    id: '',
    roleName: '',
  })
  visibale.value = false
}
//添加新角色
const addNewRole = async () => {
  // 验证输入不能为空
  const db = await form.value.validate((valid: any) => valid)
  if (!db) return
  //携带参数发送添加请求
  const result = await AddOrUpdateRole(roleData.value)
  if (result.code == 200) {
    ElMessage({
      type: 'success',
      message: roleData.value.id == '' ? '添加成功' : '修改成功',
    })
    // 成功后重置数据初始化页面
    roleData.value.id == '' ? (currentPage.value = 1) : ''
    form.value.resetFields()
    addCancle()
    getRoleInfo()
  } else {
    ElMessage({
      type: 'error',
      message: roleData.value.id == '' ? '添加失败' : '修改失败',
    })
  }
}
//角色权限信息的获取和递归算法求出已经选中的选项数据
const roleAcl = async (row: RoleRecords) => {
  // 开启遮罩，抽屉
  load.value = true
  drawer.value = true
  roleData.value.id = row.id
  roleData.value.roleName = row.roleName
  //根据角色id请求数据
  let result = await getRoleMenuById(row.id as number)
  data.value = result.data
  filterInFilter(data.value, [])
  load.value = false
}
//更新用户角色的权限分配
const updateRole = async () => {
  //加载遮罩开启
  load.value = true
  //获取已经选中的id,z这两个API都是树形控件自带的API
  let checkeds = trees.value.getCheckedKeys()
  //获取半选的id
  let checkeds2 = trees.value.getHalfCheckedKeys()
  //合并两个数组
  let pessmion = checkeds.concat(checkeds2)
  //发送请求
  const result = await reqAddUpdateAcl(roleData.value.id as number, pessmion)
  if (result.code == 200) {
    ElMessage({ type: 'success', message: '权限分配成功,手动刷新更新权限' })
    //刷新页面
    getRoleInfo()
    // 清除数据
    addCancle()
    //关闭抽屉
    drawer.value = false
    //关闭遮罩
    load.value = false
  } else {
    load.value = false
    ElMessage({ type: 'error', message: '权限分配失败' })
  }
}
//递归数据求四级id已选择的选项用于角色的权限分配
const filterInFilter = (menuArr: ResponseMenuList, inArr: any) => {
  //递归算法层层遍历，直到层级为4时才会开始push数据
  menuArr.forEach((item) => {
    if (item.select && item.level == 4) {
      inArr.push(item.id)
    }
    filterInFilter(item.children, inArr)
  })
  checkArr.value = inArr
}
//删除角色
const deleteRole = async (row: RoleRecords) => {
  const result = await deleteCurrentRole(row.id as number)
  if (result.code == 200) {
    ElMessage({ type: 'success', message: '角色删除成功' })
    getRoleInfo()
  } else {
    ElMessage({ type: 'error', message: '角色删除失败' + result.message })
  }
}
//修该用户角色失败
const rules = reactive({
  roleName: [
    { required: true, message: '不能为空', trigger: 'blur' },
    { min: 2, message: '职位名称应不小于两个字符', trigger: 'change' },
  ],
})
</script>
<style scoped lang="less"></style>
